package com.woniuxy.meal.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.meal.common.ConstantData;
import com.woniuxy.meal.common.RedisKey;
import com.woniuxy.meal.config.AlipayConfig;
import com.woniuxy.meal.entity.*;
import com.woniuxy.meal.dao.DietOrderMapper;
import com.woniuxy.meal.exception.orderException.OrderException;
import com.woniuxy.meal.exception.orderException.OrderExceptionCode;
import com.woniuxy.meal.form.AddOrderForm;
import com.woniuxy.meal.form.message.ChangeSaleMessage;
import com.woniuxy.meal.form.message.CheckOrderMessage;
import com.woniuxy.meal.form.message.DeleteCartMessage;
import com.woniuxy.meal.form.message.OrderLogMessage;
import com.woniuxy.meal.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.meal.service.dto.OrderInfoDto;
import com.woniuxy.meal.service.dto.StoreCartDto;
import com.woniuxy.meal.util.RedisUtil;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 外卖订单 服务实现类
 * </p>
 *
 * @author zz
 * @since 2023年06月12日
 */
@Service
public class DietOrderServiceImpl extends ServiceImpl<DietOrderMapper, DietOrder> implements DietOrderService {

    @Autowired
    private DietOrderMapper dietOrderMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    DietOrderFoodService dietOrderFoodService;
    @Autowired
    DietOrderLogService dietOrderLogService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private StoreInfoService storeInfoService;
    @Autowired
    private UserService userService;

    @Override
    @Transactional
    public OrderInfoDto addOrder(AddOrderForm adf, Long userId) throws Exception {
        User user = userService.getById(userId);
        StoreInfo storeInfo = storeInfoService.getById(adf.getStoreId());
        if (storeInfo==null||storeInfo.getStatus()!=1||storeInfo.getStoreStatus()!=ConstantData.STORE_STATE_OPEN){
            throw new  OrderException(5080,"下单商家不存在或者状态异常");
        }
        //构建订单
        DietOrder dietOrder = BeanUtil.toBean(adf, DietOrder.class);
        dietOrder.setOrderNum(IdUtil.getSnowflakeNextIdStr());
        dietOrder.setUserId(userId);
        dietOrder.setOrderUser(user.getUserName());
        dietOrder.setOrderDate(LocalDateTime.now());
        dietOrder.setEvaluate(0);
        dietOrder.setState(ConstantData.ORDER_WAITE_PAY);
        //构建返回dto
        OrderInfoDto orderInfoDto = BeanUtil.toBean(dietOrder,OrderInfoDto.class);
        orderInfoDto.setLogo(storeInfo.getLogo());
        orderInfoDto.setStoreName(storeInfo.getStoreName());

        //构建订单项
        List<DietOrderFood> foodList = new ArrayList<>();
        List<Long> foodIds = adf.getFoodIds();
        String userCartKey = RedisKey.getUserCartKey(userId);
        for (Long foodId : foodIds) {
            String cartInfoKey = RedisKey.getCartInfoKey(foodId);
            Object o = redisUtil.hsGet(userCartKey, cartInfoKey);
            if (o==null){
                throw new  OrderException(5081,"下单失败，请先添加购物车");
            }
            UserCart userCart = JSONUtil.toBean(String.valueOf(o), UserCart.class);
            DietOrderFood dietOrderFood = BeanUtil.toBean(userCart, DietOrderFood.class);
            dietOrderFood.setOrderNum(orderInfoDto.getOrderNum());
            foodList.add(dietOrderFood);
        }


        orderInfoDto.setItems(foodList);
        orderInfoDto.setDphPrice(adf.getDphPrice());
        orderInfoDto.setPackPrice(adf.getPackPrice());
        try {
            if (save(dietOrder)){
                dietOrderFoodService.saveBatch(foodList);
            }
        }catch (Exception e){
            throw new OrderException(OrderExceptionCode.ORDER_CREATE_FAIL);
        }

        //创建修改销售量的消息队列
        ChangeSaleMessage changeSaleMessage = new ChangeSaleMessage();
        changeSaleMessage.setList(foodList);
        changeSaleMessage.setStoreId(storeInfo.getId());
        Message<ChangeSaleMessage> changeMessage = MessageBuilder.withPayload(changeSaleMessage).build();
        rocketMQTemplate.syncSend("change_sale", changeMessage);

        //创建删除购物车的消息队列
        DeleteCartMessage deleteCartMessage = new DeleteCartMessage();
        deleteCartMessage.setUserId(userId);
        deleteCartMessage.setFoodIds(adf.getFoodIds());
        Message<DeleteCartMessage> delMessage = MessageBuilder.withPayload(deleteCartMessage).build();
        rocketMQTemplate.syncSend("carts_del", delMessage);

        //创建记录订单日志的消息队列
        OrderLogMessage orderLog = new OrderLogMessage();
        orderLog.setOrderNum(orderInfoDto.getOrderNum());
        orderLog.setOrderState("待付款");
        orderLog.setOperReason("用户下单");
        orderLog.setOperUser(dietOrder.getOrderUser());
        orderLog.setOperContent("新增订单");
        Message<OrderLogMessage> message = MessageBuilder.withPayload(orderLog).build();
        rocketMQTemplate.syncSend("orders_log", message);

        //创建10分钟后检查支付状态的消息队列
        CheckOrderMessage checkOrderMessage = new CheckOrderMessage();
        checkOrderMessage.setOderNum(orderInfoDto.getOrderNum());
        checkOrderMessage.setStoreId(orderInfoDto.getStoreId());

        List<DietOrderFood> list = BeanUtil.copyToList(foodList, DietOrderFood.class);

        for (DietOrderFood dietOrderFood : list) {
            dietOrderFood.setCount(-(dietOrderFood.getCount()));
        }
        checkOrderMessage.setList(list);
        Message<CheckOrderMessage> checkMessage = MessageBuilder.withPayload(checkOrderMessage).build();
        rocketMQTemplate.syncSend("orders_check", checkMessage,3000,15);


        return orderInfoDto;
    }

    @Override
    public String payOrder(String num) throws AlipayApiException {
        DietOrder orderInfo = getById(num);
        if (orderInfo==null){
            throw new OrderException(OrderExceptionCode.ORDER_NOT_EXIST);
        }
        if (orderInfo.getState()!=ConstantData.ORDER_WAITE_PAY){
            throw new OrderException(OrderExceptionCode.ORDER_NOT_PAY);
        }

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderInfo.getOrderNum();
        //付款金额，必填
        String total_amount = orderInfo.getPrice().toString();
        //订单名称，必填
        String subject = "点餐订单";
        //商品描述，可空
        String body = orderInfo.getStoreId()+"";

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

        //添加一个主动检查支付状态的延迟消息队列
        Message<String> checkPay = MessageBuilder.withPayload(num).build();
        rocketMQTemplate.syncSend("orders_payCheck", checkPay,3000,4);

        //请求
        return alipayClient.pageExecute(alipayRequest).getBody();
    }


    @Transactional
    @Override
    public void payCallback(DietOrder orderInfo) {
        if (orderInfo.getState()==0){

            StoreInfo storeInfo = storeInfoService.getById(orderInfo.getStoreId());
            if (storeInfo.getAutoAccept()==ConstantData.ORDER_AUTO_ACCEPT){
                orderInfo.setState(ConstantData.ORDER_ALREADY_ACCEPT);
            }
            else {
                orderInfo.setState(ConstantData.ORDER_ALREADY_PAY);
            }
            updateById(orderInfo);

            //记录日志
            DietOrderLog orderLog = new DietOrderLog();
            orderLog.setOrderNum(orderInfo.getOrderNum());
            orderLog.setOrderState("已支付");
            orderLog.setOperReason("用户支付");
            orderLog.setOperUser(orderInfo.getOrderUser());
            orderLog.setOperDate(LocalDateTime.now());
            orderLog.setOperContent("用户已经支付完成");
            dietOrderLogService.save(orderLog);
        }

    }


    public String payOrderCheck(String num){
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();

        //商户订单号，商户网站订单系统中唯一订单号
        String out_trade_no = num;

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\"}");

        //请求
        String result = null;
        try {
            result = alipayClient.execute(alipayRequest).getTradeStatus();
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        return result;
    }

    @Override
    public void cancelOrder(String oderNum,Long userId) {
        DietOrder order = getById(oderNum);
        if (order.getUserId().longValue()!=userId){
            throw new OrderException(OrderExceptionCode.ORDER_NOT_EXIST);
        }
        if (order.getState()==ConstantData.ORDER_ALREADY_FINISH){
            throw new OrderException(OrderExceptionCode.ORDER_NOT_CANCEL);
        }
        order.setState(ConstantData.ORDER_ALREADY_CANCEL);
        updateById(order);

        //创建记录日志的消息队列
        OrderLogMessage orderLog = new OrderLogMessage();
        orderLog.setOrderNum(order.getOrderNum());
        orderLog.setOrderState("已取消");
        orderLog.setOperReason("用户取消");
        orderLog.setOperUser(order.getOrderUser());
        orderLog.setOperContent("用户取消该订单");
        Message<OrderLogMessage> message = MessageBuilder.withPayload(orderLog).build();
        rocketMQTemplate.syncSend("orders_log", message);

        //创建修改销量的消息队列
        QueryWrapper<DietOrderFood> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("orderNum",order.getOrderNum());
        List<DietOrderFood> list = dietOrderFoodService.list(queryWrapper);
        for (DietOrderFood dietOrderFood : list) {
            dietOrderFood.setCount(-(dietOrderFood.getCount()));
        }
        ChangeSaleMessage changeSaleMessage = new ChangeSaleMessage();
        changeSaleMessage.setList(list);
        changeSaleMessage.setStoreId(order.getStoreId());
        Message<ChangeSaleMessage> changeMessage = MessageBuilder.withPayload(changeSaleMessage).build();
        rocketMQTemplate.syncSend("change_sale", changeMessage);


    }

    @Override
    public List<OrderInfoDto> showOrderByUserId(Long userId) throws Exception {
        QueryWrapper<DietOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",userId);
        List<DietOrder> list = list(queryWrapper);
        List<OrderInfoDto> dtoList = new ArrayList<>();
        for (DietOrder dietOrder : list) {
            StoreInfo store = storeInfoService.getById(dietOrder.getStoreId());
            OrderInfoDto orderInfoDto = BeanUtil.toBean(dietOrder, OrderInfoDto.class);
            orderInfoDto.setStoreName(store.getStoreName());
            orderInfoDto.setLogo(store.getLogo());
            QueryWrapper<DietOrderFood> wrapper = new QueryWrapper<>();
            wrapper.eq("orderNum",orderInfoDto.getOrderNum());
            List<DietOrderFood> items = dietOrderFoodService.list(wrapper);
            orderInfoDto.setItems(items);
            String state = "";
            if (orderInfoDto.getState().equals("0")){
                state = "待付款";
            }
            if (orderInfoDto.getState().equals("1")){
                state = "已付款";
            }
            if (orderInfoDto.getState().equals("2")){
                state = "已接单";
            }
            if (orderInfoDto.getState().equals("3")){
                state = "已出餐";
            }
            if (orderInfoDto.getState().equals("4")){
                state = "已完成";
            }
            if (orderInfoDto.getState().equals("5")){
                state = "已取消";
            }
            if (orderInfoDto.getState().equals("7")){
                state = "已拒单";
            }
            orderInfoDto.setState(state);
            dtoList.add(orderInfoDto);
        }
        return dtoList;
    }

}
